import Phaser from 'phaser'
import { AnimationKeys, TextureKeys } from '~/consts/Keys'

enum MouseState {
  Running,
  Killed,
  Dead
}

export default class RocketMouse extends Phaser.GameObjects.Container {
  private flames: Phaser.GameObjects.Sprite
  private mouse: Phaser.GameObjects.Sprite
  private cursors: Phaser.Types.Input.Keyboard.CursorKeys
  private mouseState = MouseState.Running // state is preserved

  constructor (scene: Phaser.Scene, x: number, y: number) {
    super(scene, x, y)

    this.flames = scene.add.sprite(-63, -15, TextureKeys.RocketMouse)
    this.add(this.flames)
    this.flames.setVisible(false)

    this.mouse = scene.add.sprite(0, 0, TextureKeys.RocketMouse)
        .setOrigin(0.5, 1)
    this.add(this.mouse) // add mouse to the container

    // animations
    this.createAnimations()
    this.flames.play(AnimationKeys.RocketFlamesOn)
    this.mouse.play(AnimationKeys.RocketMouseRun)
    
    // physics body
    scene.physics.add.existing(this)
    const body = this.body as Phaser.Physics.Arcade.Body
    body.setSize(this.mouse.width * 0.5, this.mouse.height * 0.7)
    body.setOffset(-this.mouse.width * 0.3, 15 - this.mouse.height)
    body.setCollideWorldBounds(true)
    body.setVelocityX(200)

    // arrow keys and space bar
    this.cursors = scene.input.keyboard.createCursorKeys()
  }
  // another hook
  preUpdate () {
    const body = this.body as Phaser.Physics.Arcade.Body
    if (this.mouseState === MouseState.Running) {
      if (this.cursors.space.isDown) {
        body.setAccelerationY(-600)
        this.flames.setVisible(true)
        this.mouse.play(AnimationKeys.RocketMouseFly, true)
      } else {
        body.setAccelerationY(0)
        this.flames.setVisible(false)
      }

      // decide animation to play
      if (body.blocked.down) {
        this.mouse.play(AnimationKeys.RocketMouseRun, true)
      } else if (body.velocity.y > 0) {
        this.mouse.play(AnimationKeys.RocketMouseFall, true)
      }
    } else if (this.mouseState === MouseState.Killed) {
      body.velocity.x *= 0.98 // slow down
      if (body.velocity.x < 10) {
        this.mouseState = MouseState.Dead
      }
    } else if (this.mouseState === MouseState.Dead) {
      body.setVelocity(0, 0)
      this.emit('dead')
    }
  }
  kill () {
    if (this.mouseState === MouseState.Running) {
      this.mouseState = MouseState.Killed
      this.mouse.play(AnimationKeys.RocketMouseDead)
      const body = this.body as Phaser.Physics.Arcade.Body
      body.setAccelerationY(0)
      body.setVelocity(1000, 0) // launch forward
      this.flames.setVisible(false)
    }
  }
  private createAnimations () {
    // animations
    this.mouse.anims.create({
      key: AnimationKeys.RocketMouseRun,
      // frames: [
      //   { key: 'rocket-mouse', frame: 'rocketmouse_run01.png' },
      //   { key: 'rocket-mouse', frame: 'rocketmouse_run02.png' },
      //   { key: 'rocket-mouse', frame: 'rocketmouse_run03.png' },
      //   { key: 'rocket-mouse', frame: 'rocketmouse_run04.png' },
      // ]
      frames: this.mouse.anims.generateFrameNames(TextureKeys.RocketMouse, {
        start: 1,
        end: 4,
        zeroPad: 2,
        prefix: 'rocketmouse_run',
        suffix: '.png'
      }),
      frameRate: 10,
      repeat: -1 // loop forever
    })
    this.flames.anims.create({
      key: AnimationKeys.RocketFlamesOn,
      frames: this.flames.anims.generateFrameNames(TextureKeys.RocketMouse, {
        start: 1,
        end: 2,
        prefix: 'flame',
        suffix: '.png'
      }),
      frameRate: 10,
      repeat: -1
    })
    this.mouse.anims.create({
      key: AnimationKeys.RocketMouseFly,
      frames: [{
        key: TextureKeys.RocketMouse,
        frame: 'rocketmouse_fly01.png' // 1 frame only
      }]
    })
    this.mouse.anims.create({
      key: AnimationKeys.RocketMouseFall,
      frames: [{
        key: TextureKeys.RocketMouse,
        frame: 'rocketmouse_fall01.png'
      }]
    })
    this.mouse.anims.create({
      key: AnimationKeys.RocketMouseDead,
      frames: this.mouse.anims.generateFrameNames(TextureKeys.RocketMouse, {
        start: 1,
        end: 2,
        zeroPad: 2,
        prefix: 'rocketmouse_dead',
        suffix: '.png'
      }),
      frameRate: 10
    })
  }
}